--测试环境
--package.path = package.path .. ";?.lua"
--生产环境
package.path = "./plugin/DDSU1860/utils.lua" .. ";..\\?.lua"
package.path = "./plugin/DDSU1860/json.lua" .. ";..\\?.lua"

require("utils")
require("json")


function TestEnv() --true:测试环境  false:生产环境
    if (string.find(package.path, "utils") ~= nil)
    then
        return false
    else
        return true
    end
end

rxBuf = TestEnv() == true and
    { 0xFE, 0xFE, 0xFE, 0xFE, 0x68, 0x84, 0x19, 0x11, 0x00, 0x33, 0x00, 0x68, 0x91,
        0x08, 0x33, 0x33, 0x34, 0x33, 0x33, 0x33, 0x33, 0x33, 0xE3, 0x16 } or {}


function Luaprint(str) --只在测试环境下的print
    if (TestEnv() == true)
    then
        print(str)
    end
end

-- Luaprint(package.path)
regAddr = 0x0000

function GetCRC(t, startIndex) --
    local sum = 0
    if (type(t) == "table") then
        local len = #t
        for i = startIndex, len do
            sum = sum + t[i]
        end

        if (sum > 0xff) then -- 取低八位
            sum = math.modf(sum % 256) -- s & 0xff
        end
    end
    return sum
end

function make12Len(Addr)
    local strAddr = tostring(Addr)
    local len = string.len(strAddr)
    if (len < 12) then
        for i = 1, 12 - len, 1 do
            Addr = "0" .. Addr
        end
    end
    return Addr
end

function AnalysisAddr(Addr)
    Addr = make12Len(Addr)
    local tabAddr = {}
    for i = 1, 6 do
        tabAddr[i] = tonumber(string.sub(Addr, 2 * i - 1, 2 * i), 16)
    end
    tabAddr = ReverseTable(tabAddr, false)
    return tabAddr
end

-- 解析接收的数据
function AnalysisRxData(tabRxbuf, tabBytes, index, bOffset) -- 目标table | 字节数table | 起始索引 | 结果是否减去0x33
    local tabRes = {}
    local strRes = {}

    for i = 1, #tabBytes do
        local tmp = {}
        for k = 1, tabBytes[i] do
            tmp[k] = tabRxbuf[index]
            index = index + 1
        end
        tabRes[i], strRes[i] = ReverseTable(tmp, bOffset)
    end
    return strRes, tabRes
end

-- table取反(1234变为4321)
function ReverseTable(tab, bOffset) -- 目标table | 结果是否减去0x33
    local resTable = {}
    local str = ""
    for i = 1, #tab do
        resTable[i] = tab[#tab + 1 - i] - (bOffset == true and 0x33 or 0)
        if (resTable[i] < 0) then
            resTable[i] = 256 + resTable[i]
        end
        str = str .. string.format("%02X", resTable[i])
    end
    return resTable, str
end

-- 获取指定起始位的索引
function GetStartByte(startIndex, count, tabBuf)
    for i = 1, count do
        if (tonumber(tabBuf[i]) == 0x68) then
            startIndex = i
            break
        end
    end
    return startIndex
end

function PrintTable(name, tab)
    local message = ""
    for i = 1, #tab do
        message = message .. string.format("%02X", tab[i]) .. " "
    end
    Luaprint(name .. ":" .. message)
end

-- 读
function GenerateGetRealVariables(sAddr, step)
    local addr = AnalysisAddr(sAddr)
    local requestADU = {}
    local VariableMap = {
        Status = "0",
        Variable = {},
    }
    if (step == 0) then -- 电量参数
        requestADU[1] = 0x68 -- 帧起始符68H
        requestADU[2] = addr[1] -- 地址域A0
        requestADU[3] = addr[2] -- 地址域A1
        requestADU[4] = addr[3] -- 地址域A2
        requestADU[5] = addr[4] -- 地址域A3
        requestADU[6] = addr[5] -- 地址域A4
        requestADU[7] = addr[6] -- 地址域A5
        requestADU[8] = 0x68 -- 帧起始符68H
        requestADU[9] = 0x11 -- 控制码
        requestADU[10] = 0x04 -- 数据域长度
        requestADU[11] = 0x33 -- 标识码
        requestADU[12] = 0x33 -- 标识码
        requestADU[13] = 0x34 -- 标识码
        requestADU[14] = 0x33 -- 标识码
        local crc = GetCRC(requestADU, 1)
        if (crc == nil) then
            VariableMap = {
                Status = "1",
                Variable = {}
            }
            return VariableMap
        end
        requestADU[15] = crc -- 校验码
        requestADU[16] = 0x16 -- 结束符

        VariableMap = {
            Status = "0",
            Variable = requestADU
        }

    end

    return VariableMap
end

function DeviceCustomCmd(sAddr, cmdName, cmdParam, step)
    local requestADU = {}
    local VariableMap = {
        Status = "0",
        Variable = {}
    }
    local addr = AnalysisAddr(sAddr)
    if (cmdName == "GetRealVariables") then
        if (step == 0) then -- 电量参数
            requestADU[1] = 0x68 -- 帧起始符68H
            requestADU[2] = addr[1] -- 地址域A0
            requestADU[3] = addr[2] -- 地址域A1
            requestADU[4] = addr[3] -- 地址域A2
            requestADU[5] = addr[4] -- 地址域A3
            requestADU[6] = addr[5] -- 地址域A4
            requestADU[7] = addr[6] -- 地址域A5
            requestADU[8] = 0x68 -- 帧起始符68H
            requestADU[9] = 0x11 -- 控制码
            requestADU[10] = 0x04 -- 数据域长度
            requestADU[11] = 0x33 -- 标识码
            requestADU[12] = 0x33 -- 标识码
            requestADU[13] = 0x34 -- 标识码
            requestADU[14] = 0x33 -- 标识码
            local crc = GetCRC(requestADU, 1)
            if (crc == nil) then
                VariableMap = {
                    Status = "1",
                    Variable = {}
                }
                return VariableMap
            end
            requestADU[15] = crc -- 校验码
            requestADU[16] = 0x16 -- 结束符

            VariableMap = {
                Status = "0",
                Variable = requestADU
            }
        end
    end
    return VariableMap
end

function get68Index(startIndex, tabBuf)
    if (#tabBuf == 0) then
        return 0
    end
    for i = 1 + startIndex, #tabBuf, 1 do
        if (tabBuf[i] == 0x68) then
            return i
        end
    end
    return startIndex
end

function AnalysisRx(sAddr, rxBufCnt)
    local mFunCode = 0
    local mRegByte = 0
    local crcTemp

    local VariableMap = {
        Status = "1",
        Variable = {}
    }
    -- 回应帧最短为13个字节(异常) 起始位(1)+--地址域A0-A5(6)+起始位(1)+异常控制码(1)+数据域长度(1)+错误信息字ERR(1)                    +校验码(1)+停止位(1)
    -- 回应帧最短为17个字节(正常) 起始位(1)+--地址域A0-A5(6)+起始位(1)+正常控制码(1)+数据域长度(1)+标识码(4)+数据(>=1,写数据-上电合闸状态)+校验码(1)+停止位(1)
    local addr = make12Len(sAddr) -- 通信地址

    local startIndex = 0
    startIndex = get68Index(startIndex, rxBuf)
    if (startIndex == nil or startIndex <= 0)
    then
        --Luaprint("没有找到0x68")
        rxBuf = {}
        return VariableMap
    end
    if (rxBufCnt - startIndex - 9 < 0) then
        --print("AnalysisRx -> 没有有效字节数 ")
        rxBuf = {}
        return VariableMap
    end
    mRegByte = rxBuf[startIndex + 9] -- 数据域长度
    --startIndex：起始位；9：有效位和起始位间隔；mRegByte：有效位；

    --print("AnalysisRx -> rxBufCnt == "..rxBufCnt)
    --print("AnalysisRx -> byteLength == "..(startIndex + 9 + mRegByte + 2))
    if (rxBufCnt - startIndex - 9 - mRegByte - 2 < 0) then
        --print("AnalysisRx -> 数据长度不足 ")
        rxBuf = {}
        return VariableMap
    end
    for index = 1, rxBufCnt do
        local mAddr = AnalysisRxData(rxBuf, { 6 }, startIndex + 1, false) -- 通信地址
        if (mAddr[1] == addr)
        then
            mFunCode = rxBuf[startIndex + 8] -- 控制码
            if (mFunCode == 0x91)
            then
                local byteLength = startIndex + 9 + mRegByte + 2 -- 有效字节数
                if (byteLength > #rxBuf)
                then -- 有效字节数判断
                    --Luaprint(string.format("Error! --  Out Of Range: byteLength: %s > #rxBuf: %s", byteLength, #rxBuf))
                    rxBuf = {}
                    return VariableMap
                end
                -- 暂存数据域数据
                local temp = {}
                for i = startIndex, byteLength - 2 do
                    if rxBuf[i] ~= nil then
                        table.insert(temp, rxBuf[i])
                    end
                end
                local crc = GetCRC(temp, 1)
                crcTemp = rxBuf[byteLength - 1]

                --print("AnalysisRx -> crc == "..crc)
                --print("AnalysisRx -> crcTemp == "..crcTemp)
                if (crc == crcTemp)
                then
                    local Variable = {}
                    local readRes
                    local strRes
                    local strRes1
                    local strRes2
                    local strRes3
                    local strRes4
                    local VariableIndex = 1
                    if (regAddr == 0x0000)
                    then
                        local ssIndex = get68Index(startIndex + 1, rxBuf)

                        local readQuantity = { 4 }
                        readRes = AnalysisRxData(rxBuf, readQuantity, ssIndex + 3, true)
                        if (readRes[1] == "00010000") then
                            local elecQuantity = { 4 }
                            strRes = AnalysisRxData(rxBuf, elecQuantity, ssIndex + 7, true)
                            ---------解析总有功电量数据并加入上报的map中-------------
                            local TotalEnergy = tonumber(strRes[1])

                            Variable[VariableIndex] = utils.AppendVariable(VariableIndex, "TotalEnergy", TotalEnergy,
                                "累计电量")
                            VariableIndex = VariableIndex + 1
                            VariableMap = {
                                Status = "0",
                                Variable = Variable
                            }
                        end
                    end
                    rxBuf = {}
                    return VariableMap
                end
            end
        end
    end
    rxBuf = {}
    return VariableMap
end
